﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using log4net;
using System.Configuration;
using LH.Comunicacion;
using LH.Utilitario;
using LH.Entidad;
using LH.DataAccess;
using LH.Datos;

namespace IRTPRFID
{
    public partial class ServicioRFID : ServiceBase
    {

        #region --- Variables y Propiedades ---
        Timer timerServicioLectura = new Timer();
        private static readonly ILog log = LogManager.GetLogger(typeof(ServicioRFID));

        private Servidor servidor = null;

        private Cliente cliente1 = null;
        private Cliente cliente2 = null;
        private Cliente cliente3 = null;

        private const int TIEMPO_ESPERA_COMANDO = 7500;
        private const string SEPARADOR_PARAMETRO = "|";
        private const string SIGNO_ESTACIONARIO = "Estacionario";

        private const string LLAVE_TIEMPO_ESPERA_LECTURA = "TiempoEsperaLectura";

        private ListaEtiqueta ListaEtiquetaIRTP1 = new ListaEtiqueta();
        private ListaEtiqueta ListaEtiquetaIRTP2 = new ListaEtiqueta();
        private ListaEtiqueta ListaEtiquetaIRTP3 = new ListaEtiqueta();


        #endregion

        #region --- Constructor y Destructor ---
        public ServicioRFID()
        {
            timerServicioLectura.Elapsed += timerServicioLectura_Elapsed;
            log4net.Config.XmlConfigurator.Configure();

            InitializeComponent();
        }
        #endregion

        #region --- Eventos del Servicio ---
        protected override void OnStart(string[] args)
        {
            try
            {
                log.Debug("------------------------------");
                log.Debug("Iniciando Servicio Lectura ... v20140924.0303");

                // Estableciendo parametros del timer del servicio
                timerServicioLectura.Interval = 1000 * Convert.ToInt16(ConfigurationManager.AppSettings[Constantes.SEGUNDOS_ENTRE_CADA_VERIFICACION]);
                timerServicioLectura.Enabled = true;
                timerServicioLectura.Start();

                // ------
                log.Debug("Iniciando Servidor de comunicaciones ...");
                bool resulServidor = iniciarServidor();
                if (resulServidor)
                {
                    log.Debug("Se inicio el servidor de comunicaciones");
                }

            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
        }

        protected override void OnStop()
        {
            try
            {
                timerServicioLectura.Enabled = false;

                log.Debug("-------------------------------");
                log.Debug("Deteniendo Servicio Lectura ... v20140924.0303");

                

                // -------
                log.Debug("Deteniendo Servidor de comunicaciones");
                bool resulServidor = detenerServidor();
                if (resulServidor)
                {
                    log.Debug("Se detuvo el servidor de comunicaciones");
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
        }
        #endregion

        #region --- Evento del Timer ---
        private void timerServicioLectura_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                //Se detiene el reloj
                timerServicioLectura.Stop();

                #region --carga cola1 --
                //Carga la información de cola 1
                int iLenghtIRTP1 = ListaEtiquetaIRTP1.Count();
                for (int i = 0; i < iLenghtIRTP1; i++)
                {
                    Etiqueta etiqueta = ListaEtiquetaIRTP1[i];
                    //Consulto si existe registro en BD
                    if (!new EtiquetaDA().validarRegistroIRTPRFID1(etiqueta))
                        //Si no hay lo registro
                        new EtiquetaDA().guardarRegistroIRTPRFID1(etiqueta);
                }
                ListaEtiquetaIRTP1.RemoveRange(0, iLenghtIRTP1);
                #endregion

                #region --carga cola2 --
                //Carga la información de cola 2
                int iLenghtIRTP2 = ListaEtiquetaIRTP2.Count();
                for (int i = 0; i < iLenghtIRTP2; i++)
                {
                    Etiqueta etiqueta = ListaEtiquetaIRTP2[i];
                    //Consulto si existe registro en BD
                    if (!new EtiquetaDA().validarRegistroIRTPRFID2(etiqueta))
                        //Si no hay lo registro
                        new EtiquetaDA().guardarRegistroIRTPRFID2(etiqueta);
                }
                ListaEtiquetaIRTP2.RemoveRange(0, iLenghtIRTP2);
                #endregion

                #region --carga cola3 --
                //Carga la información de cola 3
                int iLenghtIRTP3 = ListaEtiquetaIRTP3.Count();
                for (int i = 0; i < iLenghtIRTP3; i++)
                {
                    Etiqueta etiqueta = ListaEtiquetaIRTP3[i];
                    //Consulto si existe registro en BD
                    if (!new EtiquetaDA().validarRegistroIRTPRFID3(etiqueta))
                        //Si no hay lo registro
                        new EtiquetaDA().guardarRegistroIRTPRFID3(etiqueta);
                }
                ListaEtiquetaIRTP3.RemoveRange(0, iLenghtIRTP3);
                #endregion

                #region --revisa la información obtenida --
                ListaEtiqueta listaEtiquetasEvaluar = new ListaEtiqueta();
                listaEtiquetasEvaluar = new EtiquetaDA().ConsultaRegistrosValidarEstado();
                #endregion

                #region --- Ejecuta proceso en Oracle ---

                foreach (Etiqueta etiqueta in listaEtiquetasEvaluar)
                {
                    EtiquetaBien etiquetaBien = new EtiquetaDA().procesarMovimientoBien(etiqueta);

                    if (etiquetaBien.vBIncidencia.Equals("1") && etiquetaBien.vBCambio.Equals("1"))
                    {
                        //manda metodo post
                        ConexionREST conexionREST = new ConexionREST();
                        String contenidoXML = conexionREST.ejecutarOperacion(etiquetaBien);
                    }
                }
                #endregion

                //Borra a todos los registros de hace 1 minuto en rfid 1, 2 ,3 

                Boolean bEstado = false;

                bEstado = new EtiquetaDA().eliminarRegistroIRTPRFID1(DateTime.Now.AddMinutes(-1));

                bEstado = new EtiquetaDA().eliminarRegistroIRTPRFID2(DateTime.Now.AddMinutes(-1));

                bEstado = new EtiquetaDA().eliminarRegistroIRTPRFID3(DateTime.Now.AddMinutes(-1));


            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
            finally
            {

                timerServicioLectura.Start();
            }
        }
        #endregion

        #region --- Eventos del ServidorComunciaciones ---
        #region --- Cliente IRTPRFID1 ---

        private void cliente1_sucesosCliente(string mensaje)
        {
            log.Error(mensaje);
        }

        private void cliente1_recepcionData(string mensaje)
        {
            mensaje = mensaje.Substring(0, mensaje.Length - 1);

            Etiqueta etiqueta = mensaje.DeserializarTo<Etiqueta>();

            ListaEtiquetaIRTP1.Add(etiqueta);

        }

        private void cliente1_terminoConexion(string mensaje)
        {
            ListaEtiquetaIRTP1.Clear();
            ListaEtiquetaIRTP1 = null;
            log.Debug(mensaje);
        }

        #endregion

        #region --- Cliente IRTPRFID2 ---
        private void cliente2_sucesosCliente(string mensaje)
        {
            log.Error(mensaje);
        }

        private void cliente2_recepcionData(string mensaje)
        {
            mensaje = mensaje.Substring(0, mensaje.Length - 1);

            Etiqueta etiqueta = mensaje.DeserializarTo<Etiqueta>();

            ListaEtiquetaIRTP2.Add(etiqueta);
        }

        private void cliente2_terminoConexion(string mensaje)
        {

            ListaEtiquetaIRTP2.Clear();
            ListaEtiquetaIRTP2 = null;
            log.Debug(mensaje);
        }
        #endregion

        #region --- Cliente IRTPRFID3 ---
        private void cliente3_sucesosCliente(string mensaje)
        {
            log.Error(mensaje);
        }

        private void cliente3_recepcionData(string mensaje)
        {
            mensaje = mensaje.Substring(0, mensaje.Length - 1);

            Etiqueta etiqueta = mensaje.DeserializarTo<Etiqueta>();

            ListaEtiquetaIRTP3.Add(etiqueta);

        }

        private void cliente3_terminoConexion(string mensaje)
        {
            ListaEtiquetaIRTP3.Clear();
            ListaEtiquetaIRTP3 = null;
            log.Debug(mensaje);
        }
        #endregion

        #endregion

        #region --- Procedimentos ServidorComunicaciones ---
        private bool iniciarServidor()
        {
            if (iniciarCliente1() &&
                iniciarCliente2() &&
                iniciarCliente3())
                return true;
            else
                return false;

        }

        private bool iniciarCliente1()
        {
            this.cliente1 = new Cliente();
            this.cliente1.sucesosCliente += new Cliente.sucesosClienteHandler(cliente1_sucesosCliente);
            this.cliente1.recepcionData += new Cliente.recepcionDataHandler(cliente1_recepcionData);
            this.cliente1.terminoConexion += new Cliente.terminoConexionHanler(cliente1_terminoConexion);

            return this.cliente1.iniciar(ConfigurationManager.AppSettings[Constantes.IP_SERVIDOR_IRTP1], Convert.ToInt32(ConfigurationManager.AppSettings[Constantes.SERVIDOR_PUERTO_IRTP1]));
        }

        private bool iniciarCliente2()
        {
            this.cliente2 = new Cliente();
            this.cliente2.sucesosCliente += new Cliente.sucesosClienteHandler(cliente2_sucesosCliente);
            this.cliente2.recepcionData += new Cliente.recepcionDataHandler(cliente2_recepcionData);
            this.cliente2.terminoConexion += new Cliente.terminoConexionHanler(cliente2_terminoConexion);

            return this.cliente2.iniciar(ConfigurationManager.AppSettings[Constantes.IP_SERVIDOR_IRTP2], Convert.ToInt32(ConfigurationManager.AppSettings[Constantes.SERVIDOR_PUERTO_IRTP2]));
        }

        private bool iniciarCliente3()
        {
            this.cliente3 = new Cliente();
            this.cliente3.sucesosCliente += new Cliente.sucesosClienteHandler(cliente3_sucesosCliente);
            this.cliente3.recepcionData += new Cliente.recepcionDataHandler(cliente3_recepcionData);
            this.cliente3.terminoConexion += new Cliente.terminoConexionHanler(cliente3_terminoConexion);

            return this.cliente3.iniciar(ConfigurationManager.AppSettings[Constantes.IP_SERVIDOR_IRTP3], Convert.ToInt32(ConfigurationManager.AppSettings[Constantes.SERVIDOR_PUERTO_IRTP3]));
        }

        private bool detenerServidor()
        {
            bool resultado1 = false;
            bool resultado2 = false;
            bool resultado3 = false;

            resultado1 = this.cliente1.detener();
            this.cliente1.sucesosCliente -= new Cliente.sucesosClienteHandler(cliente1_sucesosCliente);
            this.cliente1.recepcionData -= new Cliente.recepcionDataHandler(cliente1_recepcionData);
            this.cliente1.terminoConexion -= new Cliente.terminoConexionHanler(cliente1_terminoConexion);

            this.cliente1 = null;

            resultado2 = this.cliente2.detener();
            this.cliente2.sucesosCliente -= new Cliente.sucesosClienteHandler(cliente2_sucesosCliente);
            this.cliente2.recepcionData -= new Cliente.recepcionDataHandler(cliente2_recepcionData);
            this.cliente2.terminoConexion -= new Cliente.terminoConexionHanler(cliente2_terminoConexion);

            this.cliente2 = null;

            resultado3 = this.cliente3.detener();
            this.cliente3.sucesosCliente -= new Cliente.sucesosClienteHandler(cliente3_sucesosCliente);
            this.cliente3.recepcionData -= new Cliente.recepcionDataHandler(cliente3_recepcionData);
            this.cliente3.terminoConexion -= new Cliente.terminoConexionHanler(cliente3_terminoConexion);

            this.cliente3 = null;

            return resultado1 && resultado2 && resultado3;
        }



        #endregion

        #region --- Procedimientos Propios ---


        private bool validarTiempoLectura(DateTime tiempoLecturaAnterior)
        {
            TimeSpan tiempoDiferencia = DateTime.Now - tiempoLecturaAnterior;
            int tiempoEsperaLectura = 0;

            tiempoEsperaLectura = Convert.ToInt32(ConfigurationManager.AppSettings[LLAVE_TIEMPO_ESPERA_LECTURA]);

            return tiempoDiferencia.TotalSeconds >= tiempoEsperaLectura;
        }

        private bool validarRegistrosMinuto(DateTime tiempoRegistro)
        {
            TimeSpan tiempoDiferencia = DateTime.Now - tiempoRegistro;
            int tiempoEsperaRegistro = 60;

            return tiempoDiferencia.TotalSeconds >= tiempoEsperaRegistro;
        }

        #endregion
    }
}
